#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <functional>

#include "Log.hpp"  //日志
#include "InetAddr.hpp"
#include "ThreadPool.hpp"

using namespace LogMudule;  //日志命名空间作用域
using namespace ThreadPoolModule;

//一些默认参数
static const int gsocketfd = -1;
static const int gbacklog = 1;
static const int gsize = 4096;


using task_t = std::function<void()>;

class TcpServer
{
private:

    //读写函数
    void Handle(int socketfd)
    {
        LOG(LogLevel::DEBUG) << "进入处理";

        char buffer[gsize];
        while (1)
        {
            // 读取
            LOG(LogLevel::DEBUG) << "进入读取";
            int n = read(socketfd, buffer, gsize - 1);

            // 读取成功，进行回显
            if (n > 0)
            {
                buffer[n] = 0;
                LOG(LogLevel::DEBUG) << "读取成功：" << buffer;

                int m = send(socketfd, buffer, n, 0);
                if (m < 0)
                {
                    LOG(LogLevel::ERROR) << "send err...";
                    break;
                }
            }
            // 客户端退出
            else if (n == 0)
            {
                LOG(LogLevel::DEBUG) << "用户退出";
                break;
            }
            // 出错
            else
            {
                LOG(LogLevel::ERROR) << "read err...";
                printf("Error occurred: %d (%s)\n", errno, strerror(errno));
                break;
            }
        }

        //关闭文件
        int n = ::close(socketfd);
        (void)n;
    }

public:
    TcpServer(uint16_t port)
        : _port(port),
          _listenfd(gsocketfd),
          _addr(port)
    {
    }

    void InitServer()
    {

        LOG(LogLevel::DEBUG) << "准备进行初始化";
        // 1.创建socket
        _listenfd = ::socket(AF_INET, SOCK_STREAM, 0);
        if (_listenfd < 0)
        {
            LOG(LogLevel::ERROR) << "socket err...";
            return;
        }

         LOG(LogLevel::DEBUG) << "socket : "<< _listenfd <<"端口号："<<_addr.GetProt();
        // 2.绑定
        int n = ::bind(_listenfd, _addr.GetAddr(), _addr.Addr_size());
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "bind err...";
            return;
        }

        // 3.设置为监听
        n = ::listen(_listenfd, gbacklog);
        if (n < 0)
        {
            LOG(LogLevel::ERROR) << "listen err...";
            return;
        }

        LOG(LogLevel::DEBUG) << "完成初始化";
    }

    void Start()
    {
        LOG(LogLevel::DEBUG) << "启动服务";

        while (1)
        {
            // 4.获取新的套接字
            struct sockaddr_in tmp;
            ::bzero(&tmp, sizeof(tmp));     //初始化tmp
            socklen_t len = sizeof(tmp);
            int socketfd = ::accept(_listenfd, (struct sockaddr *)&tmp, &len);
            if (socketfd < 0)
           { 
                continue;
            }

          LOG(LogLevel::DEBUG) << "新套接字：" << socketfd;
//             5.读取+处理+回显

            //只能处理单个客户端
            //Handle(socketfd);


            //多进程版本
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     //关闭不用的文件描述符
            //     ::close(_listenfd);

            //     //让孙子进程处理，子进程退出
            //     if(fork() > 0)
            //     {
            //         exit(0);
            //     }

            //     Handle(socketfd);
            //     exit(0);
            // }

            // int rid = ::waitpid(id,nullptr,0);
            // if(rid < 0)
            // {
            //      LOG(LogLevel::ERROR) << "waitpid err...";
            // }


            //多线程版本
            ThreadPool<task_t>::getInstance()->Equeue([this,socketfd](){this->Handle(socketfd);});
            LOG(LogLevel::DEBUG) << "加入线程池";
        }
    }

    ~TcpServer() = default;

private:
    int _listenfd;
    uint16_t _port;
    InetAddr _addr;
};
